﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataTreeLib;
using LiveSequence.Common.Domain;
using System.Reflection;

namespace LiveSequence.Common.Domain
{
  internal class MethodCallTreeHelper
  {

    public static DTreeNode<object> CreateMethodCallTree(MessageCollection messages)
    {
      DTreeNode<object> result = new DTreeNode<object>("Method");

      Queue<MessageInfo> queueMessages = new Queue<MessageInfo>(messages);
      if (queueMessages.Count > 0)
      {
        MessageInfo messageInfo = queueMessages.Peek();

        createMethodCallSubTree(messageInfo.MethodCallInfo.MethodName,
                                        messageInfo.MethodCallInfo.TypeName,
                                        result,
                                        queueMessages);
      }

      return result;
    }



    private static void createMethodCallSubTree(string strMethodCall,
                                                 string strTypeCall,
                                                 DTreeNode<object> nodeCaller,
                                                 Queue<MessageInfo> queueMethods)
    {
      while (queueMethods.Count > 0)
      {
        MessageInfo messageInfo = queueMethods.Peek();

        if ((messageInfo.MethodCallInfo.MethodName == strMethodCall) &&
          (messageInfo.MethodCallInfo.TypeName == strTypeCall))
        {
          DTreeNode<object> child = new DTreeNode<object>(messageInfo);
          nodeCaller.Nodes.Add(child);
          queueMethods.Dequeue();
          createMethodCallSubTree(messageInfo.MethodCallName,
                                          messageInfo.MethodCallInfo.MethodCallType,
                                          child,
                                          queueMethods);

        }
        else
        {
          break;
        }
      }
      
    }

    public static DTreeNode<object> GetDTreeNode(DTreeNode<object> root, object item)
    {
      DTreeNode<object> result = null;
      foreach(DTreeNode<object> child in root.Nodes)
      {
        if(child.Value == item)
        {
          result = child;
        }
        else
        {
          result = GetDTreeNode(child, item);
        }

        if(result != null)
        {
          break;
        }
      }
      return result;
    }


    internal static int NestedCallCount(DTreeNode<object> node)
    {
      int iResult = 0;

      
      foreach(DTreeNode<object> child in node.Nodes)
      {
        iResult += NestedCallCount(child);
      }

      iResult += node.Nodes.Count;
      return iResult;
    }

    internal static int GetNestedOffset(DTreeNode<object> node)
    {
      MessageInfo messageInfo = node.Value as MessageInfo;
      int iResult = 0;
      if((messageInfo != null) && (node.Parent!=null) && (!node.Parent.IsRoot))
      {
        MessageInfo parentMessageInfo = node.Parent.Value as MessageInfo;       

        if(parentMessageInfo.MethodCallInfo.TypeName == messageInfo.MethodCallInfo.TypeName)
        {
          iResult += GetNestedOffset(node.Parent) + 1;
        }

      }
      return iResult;
    }
  }
}
